﻿using System;
using System.Drawing;
using System.Collections.Generic;
using System.Windows.Forms;
using System.IO;
using System.Text;
using TagLib;
using System.Threading;
using m3u;

namespace Voize
{
    internal class CPlaylist
    {


        internal CPlaylist(ref DataGridView dPlaylist,CRandom random)
        {
            m_dPlaylist = dPlaylist;
            m_lPlaylist = new List<string>();

            m_Random = random;
        }


        private List<string> m_lPlaylist;
        private DataGridView m_dPlaylist;
        private int m_CurrentSongIndex = 0;
        private CRandom m_Random;
        private bool m_IsRandom;
        private delegate void GetNextSong();
        private delegate void GetPreviousSong();
        private delegate void SetSelectedSongDelegate(int index);
        private delegate void Delegate_AddSingleFile(string filename);
		private string m_CurrentSongName;
      


        internal void AddSingleFile(string filename)
        {
            Delegate_AddSingleFile d_add_single_file = new Delegate_AddSingleFile(Thread_AddSingleFile);
            d_add_single_file.Invoke(filename);
        }


        private void Thread_AddSingleFile(string filename)
        {
			if (System.IO.File.Exists(filename) || filename.StartsWith("http://"))
			{
				Byte[] b;
				Byte[] nb;
				string encodedfile;
				char[] c;

				b = Encoding.UTF8.GetBytes(filename);
				nb = Encoding.Convert(Encoding.UTF8, Encoding.Default, b);
				c = new char[Encoding.Default.GetCharCount(nb, 0, nb.Length)];
				Encoding.Default.GetChars(nb, 0, nb.Length, c, 0);
				encodedfile = new string(c);

				m_lPlaylist.Add(encodedfile);

				if (encodedfile.StartsWith("http://"))
				{
					CPlayerStatus.PlayListLoaded = true;
					m_dPlaylist.Rows.Add(encodedfile);
				}
				else
				{
					TagLib.File tag_file = TagLib.File.Create(filename);
					string song = tag_file.Tag.Title;
					string artist = tag_file.Tag.FirstAlbumArtist;
					CPlayerStatus.PlayListLoaded = true;

					if (artist != null)
					{
						m_dPlaylist.Rows.Add(artist + " - " + song);
					}
					else
					{
						m_dPlaylist.Rows.Add(Path.GetFileNameWithoutExtension(encodedfile));
					}
				}
			}
			
        }

       
		internal void AddUrl(string url)
		{
			CPlayerStatus.PlayListLoaded = false;
			m_lPlaylist.Add(url);
			m_dPlaylist.Rows.Add(url);
			m_dPlaylist[0, m_dPlaylist.RowCount - 2].Selected = true;
		}



        internal void RemoveFromInternalList(int index)
        {
            m_lPlaylist.RemoveAt(index);
        }



        internal void FromFolder(string path)
        {
            string[] mp3_files;
            string[] ogg_files;
            string[] s3m_files;
            string[] wav_files;
            string[] mod_files;
            string[] xm_files;
            string[] flac_files;

            mp3_files = Directory.GetFiles(path, "*.mp3", SearchOption.AllDirectories);
            ogg_files = Directory.GetFiles(path, "*.ogg", SearchOption.AllDirectories);
            s3m_files = Directory.GetFiles(path, "*.s3m", SearchOption.AllDirectories);
            wav_files = Directory.GetFiles(path, "*.wav", SearchOption.AllDirectories);
            mod_files = Directory.GetFiles(path, "*.mod", SearchOption.AllDirectories);
            xm_files =  Directory.GetFiles(path, "*.xm", SearchOption.AllDirectories);
            flac_files = Directory.GetFiles(path,"*.flac", SearchOption.AllDirectories);

            this.LoopFiles(mp3_files);
            this.LoopFiles(ogg_files);
            this.LoopFiles(s3m_files);
            this.LoopFiles(wav_files);
            this.LoopFiles(mod_files);
            this.LoopFiles(xm_files);
            this.LoopFiles(flac_files);
        }



        private void LoopFiles(string[] files)
        {
            foreach(string file in files)           
                this.AddSingleFile(file);

            files = null;
        }



        internal void Load(string filename,string root)
        {

            M3UFactory factory = new M3UFactory();
            IReader reader = factory.CreateReader();
            List<string> files = reader.Load(filename);
            
            m_dPlaylist.Rows.Clear();
            m_lPlaylist.Clear();
            
            m_CurrentSongIndex = 0;

            if (filename.EndsWith(".m3u"))
            {
                foreach (string file in files)
                {
                   this.AddSingleFile(root + file);
                }
            }
            else
            {
                foreach (string file in files)
                {
                    string[] SongArray = file.Split(';');
                    if (System.IO.File.Exists(SongArray[0]) || SongArray[0].StartsWith("http://"))
                    {
                        if (filename.EndsWith(".voize"))
                        {
                            CPlayerStatus.PlayListLoaded = true;

                            if (SongArray[0].StartsWith("http://"))
                                this.AddSingleFile(SongArray[0]);
                            else
                            {
                                if (SongArray.Length > 1)
                                {
                                    if (SongArray[1] != "" && SongArray[2] != "")
                                    {
                                        //Fast loading. If tags are ok, use this.
                                        m_lPlaylist.Add(SongArray[0]);
                                        m_dPlaylist.Rows.Add(SongArray[1] + " - " + SongArray[2]);
                                    }
                                    else
                                        this.AddSingleFile(SongArray[0]);
                                }
                                else
                                    this.AddSingleFile(SongArray[0]);
                            }
                        }
                    }
                    //else
                    //    if(System.IO.File.Exists(file))
                    //        this.AddSingleFile(root + file);//m3u
                }
            }

            files.Clear();
         }


        internal void RemoveSongFromInternalList(int index)
        {
            this.RemoveFromInternalList(index);
        }


        internal void Clear()
        {
            m_dPlaylist.Rows.Clear();
            m_lPlaylist.Clear();
            m_CurrentSongIndex = 0;

        }


        internal void ClearIndexPosition()
        {
            m_CurrentSongIndex = 0;
        }


        internal void Save(string filename)
        {
            M3UFactory factory = new M3UFactory();
            IWriter writer = factory.CreateWriter();

            if (filename.EndsWith(".m3u"))
                writer.SaveM3U(m_lPlaylist, filename);
            else
            {

                writer.Save(m_lPlaylist, filename);
            }
        }



        internal String GetSong(int i)
        {
            m_CurrentSongIndex = i;
            string song;
            song =  m_lPlaylist[i];
            if (System.IO.File.Exists(song))
                return song;
            else
                throw new Exception("Cannot find the file. File deleted or moved?");
        }



        internal int CurrentSongIndex
        {
            get { return m_CurrentSongIndex; }
            set { m_CurrentSongIndex = value; }
        }


        internal bool IsRandom
        {
            get { return m_IsRandom; }
            set { m_IsRandom = value; }
        }



        internal bool IsLastSongOnPlaylist
        {
            get
            {
                if (m_CurrentSongIndex == m_dPlaylist.RowCount - 1)
                    return true;
                else
                    return false;
            }
        }



        internal string CurrentSongNameForPopUp
        {
			get { return m_CurrentSongName; }
							//(string)m_dPlaylist[0, m_CurrentSongIndex + 1].Value; }
        }



        internal void NextSong()
        {
            Thread th = new Thread(new ThreadStart(this.NextSongInvoke));
            th.Start();
        }



        internal void PreviousSong()
        {
            Thread th = new Thread(new ThreadStart(this.PreviousSongInvoke));
            th.Start();
        }


        private void NextSongInvoke()
        {
            if (m_dPlaylist.InvokeRequired)
            {
                GetNextSong callback = new GetNextSong(CallNextSong);
                m_dPlaylist.Invoke(callback);
            }
            else
                this.CallNextSong();
        }



        private void PreviousSongInvoke()
        {
            if (m_dPlaylist.InvokeRequired)
            {
                GetPreviousSong callback = new GetPreviousSong(CallPreviousSong);
                m_dPlaylist.Invoke(callback);
            }
            else
                this.CallPreviousSong();

        }


        private void CallNextSong()
        {
            CPlayerStatus.WantChangeSong = true;
            if (IsRandom == false)
            {
                m_CurrentSongIndex += 1;
                if (m_dPlaylist.RowCount - 2 >= m_CurrentSongIndex)
                {
					m_CurrentSongName = (string)m_dPlaylist[0, m_CurrentSongIndex].Value;
                    m_dPlaylist[0, m_CurrentSongIndex].Selected = true;
                }
            }
            else
            {
                m_CurrentSongIndex = m_Random.GetRandomPlaylistRow(this.SoundCollection.Count);
				m_CurrentSongName = (string)m_dPlaylist[0, m_CurrentSongIndex].Value;
                m_dPlaylist[0, m_CurrentSongIndex].Selected = true;

            }
            CPlayerStatus.WantChangeSong = false;
        }



        private void CallPreviousSong()
        {
            CPlayerStatus.WantChangeSong = true;

            if (IsRandom == false)
            {
				if (m_dPlaylist[0, 0].Selected == false)
				{
					if (m_CurrentSongIndex <= m_dPlaylist.RowCount - 2)
					{
						m_CurrentSongIndex -= 1;
						m_dPlaylist[0, m_CurrentSongIndex].Selected = true;
					}
				}
            }
            else
            {
                m_CurrentSongIndex = m_Random.GetRandomPlaylistRow(this.SoundCollection.Count);
                m_dPlaylist[0, m_CurrentSongIndex].Selected = true;
            }

            CPlayerStatus.WantChangeSong = false;
        }



        internal void Reload()
        {         
            List<string> TempCollection = new List<string>();

            foreach (string file in this.SoundCollection)
                TempCollection.Add(file);

            this.m_dPlaylist.Rows.Clear();
            this.m_lPlaylist.Clear();

            foreach (string song in TempCollection)
                this.AddSingleFile(song);
           
            TempCollection.Clear();
        }



        internal List<string> SoundCollection
        {
            get { return m_lPlaylist; }
        }



        internal DataGridView Songs
        {
            get { return m_dPlaylist; }
        }


        internal void SetSelectedSong(int index)
        {
            if (m_dPlaylist.InvokeRequired)
            {
                SetSelectedSongDelegate sssd = new SetSelectedSongDelegate(SetSelectedSongInvoke);
                m_dPlaylist.Invoke(sssd,index);
            }
            else
            {
                SetSelectedSongInvoke(index);
            }
        }

        private void SetSelectedSongInvoke(int index)
        {
            CPlayerStatus.PlayListLoaded = false;
            CPlayerStatus.WantChangeSong = true;
            m_dPlaylist[0, index].Selected = true;

        }


    }
}
